package cn.iocoder.yudao.module.eval.service.workflow;

import cn.iocoder.yudao.module.eval.dal.dataobject.plan.EvalPlanDO;
import cn.iocoder.yudao.module.eval.service.plan.EvalPlanService;
import cn.iocoder.yudao.module.eval.service.subject.EvalSubjectService;
import cn.iocoder.yudao.module.eval.service.assignment.EvalPersonnelAssignmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.eval.enums.ErrorCodeConstants.*;

/**
 * 评价工作流 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class EvalWorkflowServiceImpl implements EvalWorkflowService {

    @Resource
    private EvalPlanService planService;
    
    @Resource
    private EvalSubjectService subjectService;
    
    // @Resource
    // private EvalPersonnelAssignmentService assignmentService;

    // 状态流转规则：当前状态 -> 允许的下一状态列表
    private static final Map<Integer, List<Integer>> STATUS_TRANSITION_RULES = new HashMap<Integer, List<Integer>>() {{
        put(0, Arrays.asList(1)); // 草稿 -> 已提交
        put(1, Arrays.asList(0, 2)); // 已提交 -> 草稿, 已审批
        put(2, Arrays.asList(3)); // 已审批 -> 已发布
        put(3, Arrays.asList(4, 6)); // 已发布 -> 进行中, 已取消
        put(4, Arrays.asList(5, 6)); // 进行中 -> 已完成, 已取消
        put(5, Collections.emptyList()); // 已完成 -> 无
        put(6, Collections.emptyList()); // 已取消 -> 无
    }};

    @Override
    public boolean isValidStatusTransition(Integer currentStatus, Integer targetStatus) {
        List<Integer> allowedStatuses = STATUS_TRANSITION_RULES.get(currentStatus);
        return allowedStatuses != null && allowedStatuses.contains(targetStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void executeStatusTransition(Long planId, Integer targetStatus, Long operatorId, String comments) {
        // 获取计划信息
        EvalPlanDO plan = planService.getPlan(planId);
        if (plan == null) {
            throw exception(PLAN_NOT_EXISTS);
        }

        Integer currentStatus = plan.getPlanStatus();
        
        // 检查状态流转是否合法
        if (!isValidStatusTransition(currentStatus, targetStatus)) {
            throw exception(PLAN_STATUS_NOT_ALLOW_UPDATE);
        }

        // 执行状态变更前的检查
        switch (targetStatus) {
            case 3: // 发布
                Object publishCheck = checkPublishConditions(planId);
                // TODO: 根据检查结果决定是否允许发布
                break;
            case 4: // 开始评价
                Object startCheck = checkStartConditions(planId);
                // TODO: 根据检查结果决定是否允许开始
                break;
            case 5: // 完成评价
                Object completeCheck = checkCompleteConditions(planId);
                // TODO: 根据检查结果决定是否允许完成
                break;
        }

        // 更新计划状态
        planService.updatePlanStatus(planId, targetStatus);

        // 发送状态变更通知
        sendStatusChangeNotification(plan, currentStatus, targetStatus, operatorId);

        // 记录状态变更日志
        log.info("计划状态变更：planId={}, {} -> {}, operator={}, comments={}", 
                planId, currentStatus, targetStatus, operatorId, comments);
    }

    @Override
    public Object getAvailableActions(Long planId) {
        EvalPlanDO plan = planService.getPlan(planId);
        if (plan == null) {
            return Collections.emptyList();
        }

        Integer currentStatus = plan.getPlanStatus();
        List<Integer> allowedStatuses = STATUS_TRANSITION_RULES.get(currentStatus);
        
        List<Map<String, Object>> actions = new ArrayList<>();
        if (allowedStatuses != null) {
            for (Integer status : allowedStatuses) {
                Map<String, Object> action = new HashMap<>();
                action.put("targetStatus", status);
                action.put("actionName", getStatusActionName(status));
                action.put("actionType", getStatusActionType(status));
                actions.add(action);
            }
        }
        
        return actions;
    }

    @Override
    public Object checkPublishConditions(Long planId) {
        Map<String, Object> result = new HashMap<>();
        List<String> errors = new ArrayList<>();
        
        // 检查是否有科目
        if (subjectService.getSubjectListByPlanId(planId).isEmpty()) {
            errors.add("计划必须包含至少一个评价科目");
        }
        
        // 检查是否分配了考评员
        // TODO: 检查考评员分配情况
        
        // 检查计划时间是否合理
        EvalPlanDO plan = planService.getPlan(planId);
        if (plan != null) {
            LocalDate now = LocalDate.now();
            if (plan.getRegistrationStartDate().isBefore(now)) {
                errors.add("报名开始时间不能早于当前时间");
            }
            if (plan.getRegistrationEndDate().isBefore(plan.getRegistrationStartDate())) {
                errors.add("报名结束时间不能早于开始时间");
            }
            if (plan.getEvaluationStartDate().isBefore(plan.getRegistrationEndDate())) {
                errors.add("评价开始时间不能早于报名结束时间");
            }
        }
        
        result.put("canPublish", errors.isEmpty());
        result.put("errors", errors);
        return result;
    }

    @Override
    public Object checkStartConditions(Long planId) {
        Map<String, Object> result = new HashMap<>();
        List<String> errors = new ArrayList<>();
        
        // 检查是否有参评人员
        // TODO: 检查参评人员情况
        
        // 检查考评员是否确认
        // TODO: 检查考评员确认情况
        
        result.put("canStart", errors.isEmpty());
        result.put("errors", errors);
        return result;
    }

    @Override
    public Object checkCompleteConditions(Long planId) {
        Map<String, Object> result = new HashMap<>();
        List<String> errors = new ArrayList<>();
        
        // 检查所有科目是否完成评分
        // TODO: 检查评分完成情况
        
        // 检查成绩是否汇总
        // TODO: 检查成绩汇总情况
        
        result.put("canComplete", errors.isEmpty());
        result.put("errors", errors);
        return result;
    }

    @Override
    public void autoAdvancePlanStatus(Long planId) {
        EvalPlanDO plan = planService.getPlan(planId);
        if (plan == null) {
            return;
        }

        LocalDate now = LocalDate.now();
        Integer currentStatus = plan.getPlanStatus();
        
        // 自动推进逻辑
        switch (currentStatus) {
            case 3: // 已发布
                if (now.isAfter(plan.getEvaluationStartDate()) || now.isEqual(plan.getEvaluationStartDate())) {
                    // 自动开始评价
                    executeStatusTransition(planId, 4, null, "系统自动开始评价");
                }
                break;
            case 4: // 进行中
                if (now.isAfter(plan.getEvaluationEndDate())) {
                    // 检查是否可以自动完成
                    Object completeCheck = checkCompleteConditions(planId);
                    // TODO: 根据检查结果决定是否自动完成
                }
                break;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchProcessPlanStatus(List<Long> planIds, Integer targetStatus, Long operatorId) {
        for (Long planId : planIds) {
            try {
                executeStatusTransition(planId, targetStatus, operatorId, "批量操作");
            } catch (Exception e) {
                log.error("批量处理计划状态失败：planId={}, targetStatus={}", planId, targetStatus, e);
            }
        }
    }

    @Override
    public void sendStatusChangeNotification(EvalPlanDO plan, Integer oldStatus, Integer newStatus, Long operatorId) {
        // TODO: 实现状态变更通知
        // 可以发送邮件、短信、系统通知等
        log.info("发送状态变更通知：planId={}, planName={}, {} -> {}", 
                plan.getId(), plan.getPlanName(), oldStatus, newStatus);
    }

    private String getStatusActionName(Integer status) {
        switch (status) {
            case 0: return "退回草稿";
            case 1: return "提交审批";
            case 2: return "审批通过";
            case 3: return "发布计划";
            case 4: return "开始评价";
            case 5: return "完成评价";
            case 6: return "取消计划";
            default: return "未知操作";
        }
    }

    private String getStatusActionType(Integer status) {
        switch (status) {
            case 0: return "warning";
            case 1: return "primary";
            case 2: return "success";
            case 3: return "success";
            case 4: return "warning";
            case 5: return "success";
            case 6: return "danger";
            default: return "default";
        }
    }

}
